package net.kelissa.divizor.util;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import net.kelissa.divizor.model.CellModel;
import net.kelissa.divizor.model.DataModel;
import net.kelissa.divizor.model.CellModel.Clazz;

public class ImageUtil
{
  static int x_size = 400;
  static int y_size = 400;
  private static Graphics2D g2D;
  private static DataResizer2D resizer;

  public ImageUtil(DataResizer2D dr)
  {
    resizer = dr;
  }

  public BufferedImage createImage() throws IOException
  {
    BufferedImage im = new BufferedImage(x_size, y_size, BufferedImage.TYPE_4BYTE_ABGR);
    g2D = im.createGraphics();
    g2D.setBackground(Color.WHITE);
    g2D.setColor(g2D.getBackground());
    g2D.fillRect(0, 0, x_size, y_size);
    return im;
  }


  public BufferedImage write(List<DataModel> l,  BufferedImage im) throws IOException
  {
    g2D = im.createGraphics();
    for (DataModel dataModel : l)
    {
      drawData(dataModel);
    }
    g2D.setColor(new Color( 0, 0, 0, 100));
    int[] point = resizer.resize(0, 0, x_size, y_size);
    g2D.drawRect(point[0]-4, point[1]-4, 8, 8);
    g2D.dispose();
    return im;
  }

  private void drawData(DataModel dataModel)
  {
    if( Const.POSITIVE.equals(dataModel.getClazzLabel()) )
      g2D.setColor(new Color( 0, 200, 0, 100));
    else
      g2D.setColor(new Color(200, 0, 0, 100));
    int[] point = resizer.resize(dataModel.getPosition()[0], dataModel.getPosition()[1], x_size, y_size);
    g2D.fillOval( point[0]-3, point[1]-3, 6, 6);

  }

  private void drawData(CellModel cell)
  {
    g2D.setColor(new Color(0,0,0, 50));
    int[] point = resizer.resize(cell.getPosition()[0], cell.getPosition()[1], x_size, y_size);
    g2D.fillOval( point[0]-5, point[1]-5, 10, 10);

  }

  public BufferedImage write( Map<Integer, CellModel> map, BufferedImage im) throws IOException
  {
    g2D = im.createGraphics();
    Set<Entry<Integer, CellModel>> entrySet = map.entrySet();

    Map<String, Integer> count = new HashMap<String, Integer>();
    for (Entry<Integer, CellModel> entry : entrySet)
    {
      count.put("" + entry.getKey() + "-UP", 0);
      count.put("" + entry.getKey() + "-DOWN", 0);
    }
    Map<String, Color> colors = calcColors(map);
    for (int y = 0; y < y_size; y++)
      for (int x = 0; x < x_size; x++)
      {
        double[] inversePosition = resizer.inverseResize(x, y, x_size, y_size);
        int neighbor = MathUtil.neighbor(map, inversePosition);
        Clazz clazz = MathUtil.calcClass( map.get(neighbor), inversePosition);
        if(clazz.equals(CellModel.Clazz.UP))
        {
          count.put("" + neighbor + "-UP", count.get("" + neighbor + "-UP") + 1);
          g2D.setColor(colors.get("" + neighbor + "-UP"));
        }
        else
        {
          count.put("" + neighbor + "-DOWN", count.get("" + neighbor + "-DOWN") + 1);
          g2D.setColor(colors.get("" + neighbor + "-DOWN"));
        }
        g2D.fillRect(x, y, 1, 1);
      }

    for (Entry<Integer, CellModel> entry : entrySet)
    {
      drawData(entry.getValue());
    }

    g2D.dispose();
    return im;
  }

  private Map<String, Color> calcColors(Map<Integer, CellModel> map)
  {
    Map<String, Color> res = new HashMap<String, Color>();
    Set<Entry<Integer, CellModel>> entrySet = map.entrySet();
    for (Entry<Integer, CellModel> entry : entrySet)
    {
      String upClass = entry.getValue().getClassLabelUp();
      res.put("" + entry.getKey() + "-UP", calcRandColor(upClass));

      String downClass = entry.getValue().getClassLabelDown();
      res.put("" + entry.getKey() + "-DOWN", calcRandColor(downClass));
    }
    return res;
  }

  private Color calcRandColor(String label)
  {
    Color color;
    int rand1 = MathUtil.getRandom().nextInt(80)-40;
    int rand2 = MathUtil.getRandom().nextInt(80)-40;
    if(Const.POSITIVE.equals(label))
    {
      color = new Color(210 + rand1, 255, 200 + rand2);
    }
    else
    {
      color = new Color(255, 160 + rand1, 210 + rand2);
    }
    return color;
  }

}
